#ifndef LOMTRANSACTIONSYSTEMHH
#define LOMTRANSACTIONSYSTEMHH
#include "lom-typedefs.hh"
#include "lom-events.hh"

namespace lom
{
    class ILomValueFactory;

    
    class ILomTransactionHandler
    {
    public:
	virtual ~ILomTransactionHandler(){}
	virtual void beginTransactionEvents() = 0;
	virtual void handle( const ILomTransactionEvent* evt ) = 0;
	virtual void endTransactionEvents() = 0;
    };

    class ILomTransactionSystem
    {
    public:
	virtual ~ILomTransactionSystem(){}
	
	virtual void addHandler( ILomTransactionHandler* handler ) = 0;
	virtual void removeHandler( ILomTransactionHandler* handler ) = 0;
	//Begin listening to events and recording them
	virtual void beginTransaction( ILomTransactionHandler* activeHandler ) = 0;
	//Run through list and send events to everyone *but* the active handler.
	virtual void endTransaction() = 0;
    };

    class LomTransactionGuard
    {
	ILomTransactionSystem* system;
    public:
	LomTransactionGuard( ILomTransactionSystem* _system
			     , ILomTransactionHandler* _handler ) {
	    system = _system;
	    if ( system )
		system->beginTransaction( _handler );
	}
	
	~LomTransactionGuard() {
	    if ( system )
		system->endTransaction();
	    system = NULL;
	}
    };
    
    
    class LomTransactionSystem : public ILomEventHandler, public ILomTransactionSystem
    {
	TLomTransactionHandlerVector handlers;
	TLomTransactionEventVector currentEvents;
	//Cache created events so I don't keep creating things.
	TLomTransactionEventVectorUInt32PairVector eventCache;
	ILomValueFactory* valueFactory;
	ILomTransactionHandler* activeHandler;
	
	//Cached intermediate values
	TValueVector valueVector;
	licada::TNameStr nameStr;
	ILomEventSystem* eventSystem;
	
    public:
	LomTransactionSystem();
	virtual ~LomTransactionSystem();
	
	virtual void resetLomTransactionSystem();
	virtual void setupLomTransactionSystem( ILomValueFactory* _valueFactory
						, ILomEventSystem* eventSystem );
	
	virtual void addHandler( ILomTransactionHandler* handler );
	virtual void removeHandler( ILomTransactionHandler* handler );
	//Begin listening to events and recording them
	virtual void beginTransaction( ILomTransactionHandler* activeHandler );
	//Run through list and send events to everyone *but* the active handler.
	virtual void endTransaction();

	virtual void event( licada::TNameType name, const TValueVector& args );
	virtual void classCreated( const LomClass& cls );
	virtual void instanceCreated( THandle instance );
	virtual void instanceDestroyed( THandle instance );
	virtual void propertyEvent( THandle instance
				    , licada::uint32 propIndex
				    , const LomValue& finalValue );
	/**
	   The lom system defines a root context with a set of
	   key-value pairs.  When something changes the root context,
	   this event is sent.
	 */
	virtual void rootObjectSet( licada::TNameType name, const LomValue& value ) ;

    private:
	ILomTransactionEvent* getOrCreateEvent( ETransactionEventType type );
    };
}
#endif
